package com;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

import clases.Entidad;
import clases.EntidadCorazon;
import clases.EntidadDisparo;
import clases.EntidadJugador;
import clases.EntidadPared;
import clases.Usuario;

import utils.CapturarTeclado;
import utils.ConexionDB;
import utils.Constantes;
import utils.ConsultasDB;

public class Juego extends Canvas {
	
	private ArrayList<Entidad> entidades = new ArrayList<Entidad>();
	private ArrayList<Entidad> entidadesBorrar = new ArrayList<Entidad>();
	private CapturarTeclado teclado;
	private CapturarTeclado teclado2;
	private Entidad jugador;
	private Entidad jugador2;
	private String mensaje = "";
	private long intervaloDisparo = 500;
	private boolean juegoFuncionando = true;
	private BufferStrategy estrategia;
	
	
	public Juego(){
		JFrame container = new JFrame("I Wanna Be The Shooter");
		JPanel panel = (JPanel) container.getContentPane();
		panel.setPreferredSize(new Dimension(800,600));
		panel.setLayout(null);
		setBounds(0,0,810,610);
		panel.add(this);
		setIgnoreRepaint(true);		
		container.pack();
		container.setResizable(false);
		container.setVisible(true);
		
		container.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		// Se capturan las teclas que van a utilizarse para cada jugador.
		
		teclado = new CapturarTeclado(Constantes.TECLADO_JUGADOR1_IZQUIERDA,
									  Constantes.TECLADO_JUGADOR1_DERECHA,
									  Constantes.TECLADO_JUGADOR1_ABAJO,
									  Constantes.TECLADO_JUGADOR1_ARRIBA,
									  Constantes.TECLADO_JUGADOR1_DISPARAR);
		teclado2 = new CapturarTeclado(Constantes.TECLADO_JUGADOR2_IZQUIERDA,
									   Constantes.TECLADO_JUGADOR2_DERECHA,
									   Constantes.TECLADO_JUGADOR2_ABAJO,
									   Constantes.TECLADO_JUGADOR2_ARRIBA,
									   Constantes.TECLADO_JUGADOR2_DISPARAR);
									
		addKeyListener(teclado);
		addKeyListener(teclado2);
		requestFocus();

		createBufferStrategy(2);
		estrategia = getBufferStrategy();

		inicializar();
	}	

	
	private void menu()
	{				
		try {		
			
			seleccionarJugador(1);
			seleccionarJugador(2);		
			
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}
	
	private void seleccionarJugador(int numeroJugador)
	{
		teclado.setWaitingForKeyPress(true);
		List<Usuario> listaUsuarios;
		listaUsuarios = ConsultasDB.RecuperarUsuarios(ConexionDB.getConexion());		
		int posicion = 200;
		String jugadorElegido;
		boolean esperar = true;
		Usuario userEncontrado = null;
		while (teclado.isWaitingForKeyPress() || esperar) {			

			Graphics2D g = (Graphics2D) estrategia.getDrawGraphics();
			Image imagen = new ImageIcon(getClass().getClassLoader().getResource("sprites/fondo.gif")).getImage();
			g.drawImage(imagen, 0, 0,getWidth(), getHeight(),this);	
			
			if (mensaje!=null && mensaje!="")
			{
				g.setColor(Color.white);
				g.drawString(mensaje,(800-g.getFontMetrics().stringWidth(mensaje))/2,250);
				g.drawString("Pulsa una tecla para nueva partida",(800-g.getFontMetrics().stringWidth("Pulsa una tecla para nueva partida"))/2,300);	
				if (teclado.getTeclaPulsada()!=null)
				{
					mensaje=null;
				}
			}
			else
			{
				if (teclado.getTeclaPulsada()!=null )
				{
					jugadorElegido = String.valueOf(teclado.getTeclaPulsada());
					if(jugadorElegido.equals("0"))
					{						
						crearJugador();
						listaUsuarios = ConsultasDB.RecuperarUsuarios(ConexionDB.getConexion());	
					}
					
					if(jugadorElegido.equals("d"))
					{	
						borrarJugador();
						listaUsuarios = ConsultasDB.RecuperarUsuarios(ConexionDB.getConexion());	
					}
					
					
					for(Usuario user : listaUsuarios)
					{
						if (user.getId().equals(jugadorElegido))
						{
							teclado.setTeclaPulsada(null);
							userEncontrado=user;
						}
					}
					if (userEncontrado!=null)
					{							
						if (numeroJugador==1)
						{
							((EntidadJugador)jugador).setNombreJugador(userEncontrado.getNombre());
							((EntidadJugador)jugador).setIdJugador(userEncontrado.getId());		
						}
						else
						{
							((EntidadJugador)jugador2).setNombreJugador(userEncontrado.getNombre());	
							((EntidadJugador)jugador2).setIdJugador(userEncontrado.getId());							
						}
						esperar = false;			
					}
					else
					{
						teclado.setWaitingForKeyPress(true);
					}
				}
				
			    
				g.setColor(Color.white);
				g.drawString("Selecciona Jugador "+numeroJugador,(800-g.getFontMetrics().stringWidth("Selecciona Jugador "+numeroJugador))/2,posicion);	
				posicion = posicion+25;
				g.drawString("0 - Nuevo Jugador",(800-g.getFontMetrics().stringWidth("0 - Nuevo Jugador"))/2,posicion);
				posicion = posicion+25;
				g.drawString("d - Borrar Jugador",(800-g.getFontMetrics().stringWidth("d - Borrar Jugador"))/2,posicion);
	
				for (Usuario user: listaUsuarios)
				{
					posicion = posicion+25;
					g.drawString(user.getId()+".- "+user.getNombre()+" - Victorias: "+user.getPuntuacion(),(800-g.getFontMetrics().stringWidth(user.getId()+".-"+user.getNombre()+" - Victorias: "+user.getPuntuacion()))/2,posicion);	
				}	
				posicion = 300;
			}
			
			g.dispose();
			estrategia.show();

			try { Thread.sleep(10); } catch (Exception e) {}
		}
		
	}
	
	private void borrarJugador()
	{
		List<Usuario> listaUsuarios;
		listaUsuarios = ConsultasDB.RecuperarUsuarios(ConexionDB.getConexion());		
		int posicion = 200;
		String jugadorElegido;
		boolean esperar = true;
		Usuario userEncontrado = null;
		
		while (teclado.isWaitingForKeyPress() || esperar) {			

			Graphics2D g = (Graphics2D) estrategia.getDrawGraphics();
			Image imagen = new ImageIcon(getClass().getClassLoader().getResource("sprites/fondo.gif")).getImage();
			g.drawImage(imagen, 0, 0,getWidth(), getHeight(),this);	
		
			if (teclado.getTeclaPulsada()!=null )
			{
				jugadorElegido = String.valueOf(teclado.getTeclaPulsada());
									
				for(Usuario user : listaUsuarios)
				{
					if (user.getId().equals(jugadorElegido))
					{
						teclado.setTeclaPulsada(null);
						userEncontrado=user;
					}
				}
				if (userEncontrado!=null)
				{		
					ConsultasDB.borrarUsuario(ConexionDB.getConexion(), jugadorElegido);
					esperar = false;			
				}
				else
				{
					teclado.setWaitingForKeyPress(true);
				}
			}
			
		    
			g.setColor(Color.white);
			g.drawString("Selecciona Jugador a BORRAR",(800-g.getFontMetrics().stringWidth("Selecciona Jugador a BORRAR"))/2,posicion);	

			for (Usuario user: listaUsuarios)
			{
				posicion = posicion+25;
				g.drawString(user.getId()+".-"+user.getNombre(),(800-g.getFontMetrics().stringWidth(user.getId()+".-"+user.getNombre()))/2,posicion);	
			}	
			posicion = 300;
			
			
			g.dispose();
			estrategia.show();

			try { Thread.sleep(10); } catch (Exception e) {}
		}
	}

	
	private void crearJugador() {
		
		List<String> TeclasPulsadas = new ArrayList<String>();
		int tecla;
		String letra;
		boolean esperar = true;
		
		while (teclado.isWaitingForKeyPress() || esperar) {			

			Graphics2D g = (Graphics2D) estrategia.getDrawGraphics();
			Image imagen = new ImageIcon(getClass().getClassLoader().getResource("sprites/fondo.gif")).getImage();
			g.drawImage(imagen, 0, 0,getWidth(), getHeight(),this);	
			
				if (teclado.getTeclaPulsada()!=null )
				{
					tecla = Integer.valueOf(teclado.getTeclaPulsada());
					letra = String.valueOf(teclado.getTeclaPulsada());
					
					teclado.setTeclaPulsada(null);
					teclado.setWaitingForKeyPress(true);

					if((tecla==KeyEvent.VK_BACK_SPACE) && TeclasPulsadas.size()>0)
					{	
						TeclasPulsadas.remove(TeclasPulsadas.size()-1);
					}

					if((tecla==KeyEvent.VK_ENTER) && TeclasPulsadas.size()>0)
					{		
						String NombreFinal = "";
						for(String letraActual : TeclasPulsadas)
						{
							NombreFinal = NombreFinal+letraActual;
						}
						ConsultasDB.crearUsuario(ConexionDB.getConexion(),NombreFinal);
						teclado.setWaitingForKeyPress(false);		
						esperar = false;
					}					
					
					if ((tecla > KeyEvent.VK_0) && (tecla < 123))
					{
						TeclasPulsadas.add(letra);
					}
				}
				
				int horizontal = 830;
			    
				g.setColor(Color.white);
				g.drawString("Nuevo Jugador",(800-g.getFontMetrics().stringWidth("Nuevo Jugador"))/2,300);	
				g.drawString("Nombre:",(800-g.getFontMetrics().stringWidth("Nuevo Jugador"))/2,340);	
				
				for(String teclaPulsada : TeclasPulsadas)
				{
					g.drawString(teclaPulsada,(horizontal-g.getFontMetrics().stringWidth(teclaPulsada))/2,340);	
					horizontal = horizontal+15;
				}				
			
			g.dispose();
			estrategia.show();

			try { Thread.sleep(10); } catch (Exception e) {}
		}
	}


	private void iniciarJuego() {
		entidades.clear();
		inicializar();
		
		// Al iniciar el juego, todas las teclas se establecen en false, para indicar que no estan pulsadas. 

		teclado.setLeftPressed(false);
		teclado.setRightPressed(false);
		teclado.setDownPressed(false);
		teclado.setUpPressed(false);
		teclado.setFirePressed(false);
		teclado2.setLeftPressed(false);
		teclado2.setRightPressed(false);
		teclado2.setFirePressed(false);
		teclado2.setDownPressed(false);
		teclado2.setUpPressed(false);
	}
	
	private void inicializarJugadores()
	{		
		jugador = new EntidadJugador(this,"sprites/shipAr.gif",Constantes.POSICION_INICIAL_JUGADOR_1_X,Constantes.POSICION_INICIAL_JUGADOR_1_Y,Constantes.NUMERO_VIDAS_JUGADOR1,teclado,"J1",1);
		entidades.add(jugador);
		jugador2 = new EntidadJugador(this,"sprites/shipAr.gif",Constantes.POSICION_INICIAL_JUGADOR_2_X,Constantes.POSICION_INICIAL_JUGADOR_2_Y,Constantes.NUMERO_VIDAS_JUGADOR2,teclado2,"J2",2);
		entidades.add(jugador2);			
	}
	
	private void inicializar() {	
		
		// Al inicializar, se utiliza el constructor EntidadJugador para crear ambos jugadores, y el constructor EntidadPared para las paredes.
		inicializarJugadores();
		menu();
		
		for (int i=0; i<22; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredLa.gif",50+(32*i),50);
			entidades.add(pared1);
		}
		
		for (int i=0; i<16; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredAr.gif",50,50+(32*i));
			entidades.add(pared1);
		}
		
		for (int i=0; i<22; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredLa.gif",51+(32*i),553);
			entidades.add(pared1);
		}
		
		for (int i=0; i<16; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredAr.gif",750,50+(32*i));
			entidades.add(pared1);
		}
		
		for (int i=0; i<10; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredAr.gif",150,150+(32*i));
			entidades.add(pared1);
		}
		
		for (int i=0; i<12; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredLa.gif",160+(32*i),460);
			entidades.add(pared1);
		}
		
		for (int i=0; i<10; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredAr.gif",650,150+(32*i));
			entidades.add(pared1);
		}
		
		for (int i=0; i<12; i++){
			Entidad pared1 = new EntidadPared(this,"sprites/paredLa.gif",277+(32*i),150);
			entidades.add(pared1);
		}
	}
	
	public void removerEntidad(Entidad entidad) {
		entidadesBorrar.add(entidad);
	}
	
	
	public void notificarMuerte(EntidadJugador jugador) {
		jugador.getTeclado().setWaitingForKeyPress(true);
		teclado.setTeclaPulsada(null);
		mensaje = jugador.getNombreJugador() + " ha sido reducido a cenizas.";
		if (((EntidadJugador)this.jugador).getIdJugador()!=jugador.getIdJugador())
		{
			ConsultasDB.sumarVictoria(ConexionDB.getConexion(), ((EntidadJugador)this.jugador).getIdJugador());
		}		
		else
		{
			ConsultasDB.sumarVictoria(ConexionDB.getConexion(), ((EntidadJugador)this.jugador2).getIdJugador());			
		}
		iniciarJuego();
	}

	public void intentarDisparar(EntidadJugador jugador) {
		
		if (System.currentTimeMillis() - jugador.getUltimoDisparo() < intervaloDisparo) {
			return;
		}
		
		jugador.setUltimoDisparo(System.currentTimeMillis());
		EntidadDisparo shot = new EntidadDisparo(this,jugador.getX(),jugador.getY(),jugador.getOrientacion());
		entidades.add(shot);
	}	
	
	public void Comenzar() {
		long lastLoopTime = System.currentTimeMillis();

		while (juegoFuncionando) {
			long delta = System.currentTimeMillis() - lastLoopTime;
			lastLoopTime = System.currentTimeMillis();
			
			Graphics2D g = (Graphics2D) estrategia.getDrawGraphics();
			Image imagen = new ImageIcon(getClass().getClassLoader().getResource("sprites/fondo.gif")).getImage();
			g.drawImage(imagen, 0, 0,getWidth(), getHeight(),this);	
		    

			if (!teclado.isWaitingForKeyPress()) {
				for (int i=0;i<entidades.size();i++) {
					Entidad entity = (Entidad) entidades.get(i);					
					entity.move(delta);
				}
			}
			
			for (int i=0;i<entidades.size();i++) {
				Entidad entity = (Entidad) entidades.get(i);	
				if (entity instanceof EntidadJugador)
				{
					for(EntidadCorazon corazon :((EntidadJugador) entity).getVidasSprite())
					{
						corazon.dibujar(g);
					}
				}
				entity.dibujar(g);
			}
			
			for (int p=0;p<entidades.size();p++) {
				for (int s=p+1;s<entidades.size();s++) {
					Entidad me = (Entidad) entidades.get(p);
					Entidad him = (Entidad) entidades.get(s);
					
					if (me.hacolisionado(him)) {
						me.colisionacon(him);
						him.colisionacon(me);
					}
				}
			}
			
			entidades.removeAll(entidadesBorrar);
			entidadesBorrar.clear();
/*
			if (logicRequiredThisLoop) {
				for (int i=0;i<entities.size();i++) {
					Entidad entity = (Entidad) entities.get(i);
					entity.doLogic();
				}
				
				logicRequiredThisLoop = false;
			}*/

			if (teclado.isWaitingForKeyPress() || teclado2.isWaitingForKeyPress()) {
				g.setColor(Color.white);
				g.drawString(mensaje,(800-g.getFontMetrics().stringWidth(mensaje))/2,250);
				g.drawString("Pulsa una tecla para nueva partida",(800-g.getFontMetrics().stringWidth("Pulsa una tecla para nueva partida"))/2,300);
			}
			else
			{
				((EntidadJugador) jugador).gestionarMovimiento(teclado);
				((EntidadJugador) jugador2).gestionarMovimiento(teclado2);
			}
			
			g.dispose();
			estrategia.show();

			try { Thread.sleep(10); } catch (Exception e) {}
		}
	}
	
}
